Room Manager
TheManager type in /internal/room/manager.go coordinates all rooms:
Thread-Safe Operations
The manager usessync.RWMutex for concurrent access:
- RLock/RUnlock: Used for read operations (GetRoom, RoomCount, GetAIClient)
- Lock/Unlock: Used for write operations (CreateRoom, LeaveRoom)
Room Structure
Each room contains:Key Fields
- ID: UUID generated at creation time
- Description: Optional user-provided description (used for workspace naming)
- Host: Username of the room creator
- Connections: List of connected clients
- Terminal: Shared terminal instance (nil until first client starts it)
- AIMessages: Conversation history for AI chat feature
- WorkspaceDir: Isolated filesystem directory for this room
Client Structure
- Unique ID: UUID to distinguish multiple connections from same user
- Display name: From SSH session username
- Host flag: Only the creator has this set to true
- Event channel: Receives room events (join/leave/typing/ai_sync)
Room Lifecycle
1. Room Creation
- If description provided:
slugify("My Project")→my-project - Otherwise: random name like
cosmic-phoenixorbrave-dragon
/app/workspace-template/ contents into each workspace, providing pre-configured files or tools. Falls back to an empty directory if template is unavailable.
2. Joining a Room
3. Client Registration
In the UI model (/internal/ui/model.go):
select with default case ensures event sends never block. If a client’s event channel is full, the event is dropped for that client.
4. Leaving a Room
- Remove client from room’s connection list
- If last client:
- Close terminal and kill shell process
- Delete workspace directory from filesystem
- Send DELETE request to worker (if configured) to clean up sandbox and AI state
- Remove room from manager’s map
5. Resource Cleanup
External resources are cleaned up asynchronously:Event Broadcasting
Room Events
join: User joined the roomleave: User left the roomtyping: User is typing in terminal (debounced to 500ms)ai_sync: AI chat messages updated (triggers viewport refresh)
Broadcast Implementation
excludeClientID parameter prevents echoing events back to the sender.
Workspace Isolation
Each room’s workspace provides:Directory Structure
Template Files
If/app/workspace-template/ exists, it’s copied to each workspace:
Terminal Working Directory
When starting the terminal:cmd.Dir = workDir, providing filesystem isolation.
AI Message Synchronization
Rooms store AI conversation history:Thread-Safe Access
Sync Flow
- Client sends AI message via
Ctrl+G - Worker returns updated message history
- Client calls
currentRoom.SetAIMessages(msgs) - Client broadcasts
ai_syncevent - Other clients receive event and call
GetAIMessages()to refresh their viewport
Concurrency Patterns
Read-Heavy Optimization
sync.RWMutex is used because:
- Reads (GetRoom, RoomCount) are frequent (every client action)
- Writes (CreateRoom, LeaveRoom) are infrequent (only on join/leave)
Channel-Based Events
Each client has a buffered channel (chan RoomEvent, 10) that:
- Decouples event producers (broadcast) from consumers (client UI loop)
- Prevents blocking if client is slow to process
- Automatically closes when client disconnects